package com.eobard.mq.consumer;

import com.eobard.constant.SecKillConstant;
import com.eobard.dto.ProductSeckillDto;
import com.eobard.enums.SecKillEnum;
import com.eobard.service.ProductService;
import com.eobard.utils.SecKillUtils;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

/**
 * @Author: Eobard Gu
 * @Date: 2025-07-18
 * @Description: TODO
 */
@Component
@Slf4j
public class ProductConsumer {

    @Autowired
    private ProductService productService;

    @Autowired
    private SecKillUtils secKillUtils;

    @RabbitListener(bindings = @QueueBinding(
            //绑定队列,并对消息进行持久化
            value = @Queue(value = SecKillConstant.SECKILL_QUEUE, durable = "true"),
            //绑定交换机
            exchange = @Exchange(value = SecKillConstant.SECKILL_EXCHANGE),
            //绑定路由Kye
            key = {SecKillConstant.SECKILL_KEY}
    ))
    public void seckill(ProductSeckillDto seckillDto, Message message, Channel channel) throws IOException {
        String userId = seckillDto.userId();
        Long productId = seckillDto.productId();
        String secKillId = seckillDto.secKillId();
        try {
            SecKillEnum purchased = productService.purchase(userId, productId);
            secKillUtils.updateSecKillStatus(secKillId, purchased.msg);
            //手动ack
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            secKillUtils.updateSecKillStatus(secKillId, SecKillEnum.RETRY.msg);
            //手动拒绝确认消息,并重新入队,如果不重新入队(如果配置了死信队列的话将会进入死信队列),否则将直接丢弃消息
            //(long deliveryTag, boolean multiple, boolean requeue)
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
    }
}